###################################################
# Tecnologico de Costa Rica                       #
# Introduccion a los Sistemas Embebidos           #
# II Semestre - 2013                              #
###################################################
# Proyecto 2 - DotAMemory Game                    #
###################################################
# Cristian Brenes Quiros                          #
# Alejandro Morales Araya                         #
# Pedro Rojas Barrett                             #
###################################################

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygtk
pygtk.require('2.0')
import gtk
import gobject
import pygst
pygst.require('0.10')
gobject.threads_init()
import gst
import time
import random
from Tkinter import * 
from PIL import Image, ImageTk
import threading

def get_cards():
    return [i%8 for i in range(16)]#arreglo de 16, numeros del 0-7
def init_exposed():
    return [False for i in range(16)]


        #############################################
        ## GStreamer/PocketSphinx Demo Application ##
        #############################################

class DemoApp(object):
    def __init__(self):
        
        self.t1 = threading.Thread(target=self.init_gui)  
        self.t1.start()
        self.t2 = threading.Thread(target=self.init_gst)
        self.t2.start()
        self.t3 = threading.Thread(target=self.init_Tk)  
        self.t4 = threading.Thread(target=self.activate_speak)  
        
        #self.tick()
         
        global cards,exposed,moves, card1,card2,state,B1,B2,PosX,PosY
        cards=get_cards()
        random.shuffle(cards)
        self.PosX = 0
        self.PosY = 0
        self.card1 = -1
        self.card2 = -1
        self.global_state = 0
        
        self.remaining = 8
        self.moves = 0
        self.points = 0
        self.game_time = time.clock()
        self.start_time = ''
        self.time3 = ''
        

        
        self.IconImages = [Image.open("/home/cy/sphinx/python/images/dota.jpg"),
                          Image.open("/home/cy/sphinx/python/images/aegis.jpg"),
                          Image.open("/home/cy/sphinx/python/images/win.jpg")]
        self.HeroImages = [Image.open("/home/cy/sphinx/python/images/"+str(i)+".jpg") for i in range(8)]
        #self.buttons = [0][0]
        #self.photo = [0]
        #self.heroPhoto = [0]

        ##################################################
        ## Inicializacion de interfaz de bienvenida-GTK ##
        ##################################################

    def init_gui(self):
        """Initialize the GUI components"""
        self.window = gtk.Window()
        self.window.connect("delete-event", gtk.main_quit)
        self.window.set_default_size(600,400)
        self.window.set_title("MEMORY")
        self.window.set_border_width(10)
        vbox = gtk.VBox()
        self.textbuf = gtk.TextBuffer()
        self.text = gtk.TextView(self.textbuf)
        self.text.set_wrap_mode(gtk.WRAP_WORD)
        vbox.pack_start(self.text)
        self.speak_button = gtk.ToggleButton("Hablar")
        self.speak_button.connect('clicked', self.speak_clicked)

        self.accept_button = gtk.ToggleButton("Aceptar")
        self.accept_button.connect('clicked', self.accept_clicked)
        self.cancel_button = gtk.ToggleButton("Borrar")
        self.cancel_button.connect('clicked', self.cancel_clicked)

        vbox.pack_start(self.speak_button, False, False, 5)
        vbox.pack_start(self.accept_button, False, False, 6)
        vbox.pack_start(self.cancel_button, False, False, 7)
        self.window.add(vbox)
        self.window.show_all()

        #################################################
        ## Inicializacion de interfaz de juego Tkinter ##
        #################################################

    def init_Tk(self):
        self.root = Tk()
        self.root["bg"] = "black"
        self.root.title("DotAMemorY")
        #root["title"] = "DotAMemorY"
        size = 4            
        self.photo = [ImageTk.PhotoImage(self.IconImages[0]),ImageTk.PhotoImage(self.IconImages[1]),
                      ImageTk.PhotoImage(self.IconImages[2])]
        self.heroPhoto = [ImageTk.PhotoImage(self.HeroImages[i]) for i in range(8)]
        
        self.buttons = [[Button(self.root) for i in range(size)]for j in range(size)]
        for i in range(size):
            for j in range(size):
                self.buttons[i][j].grid(row=i, column=j)
                self.buttons[i][j]["image"] = self.photo[0]
                self.buttons[i][j]["command"] = eval("self.button"+str(i+j+(size-1)*i)+"_clicked")
                self.buttons[i][j]["bg"] = "black"            
        self.buttons[self.PosY][self.PosX]["bg"] = "green"
        
        self.QUIT = Button(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0)
        self.QUIT["text"] = "QUIT"
        self.QUIT["fg"]   = "red"
        self.QUIT["command"] =  self.quit_game
        self.QUIT.grid(row=8, column=0)

        self.hi_there = Button(self.root, font=('ubuntu', 14, 'bold'), bg='black', fg='white', bd=0)
        self.hi_there["text"] = "RESTART",
        self.hi_there["command"] = self.restart_game
        self.hi_there.grid(row=8, column=3)
        
        self.show_moves = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text=0)
        self.show_moves.grid(row=7,column=1)
        self.show_moves2 = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text="MOVES")
        self.show_moves2.grid(row=7,column=0)

        
        self.show_time = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text=0) 
        self.show_time.grid(row=7,column=3)
        self.show_time2 = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text="TIME") 
        self.show_time2.grid(row=7,column=2)
        
        self.show_points = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text=0) 
        self.show_points.grid(row=8,column=2)
        self.show_points2 = Label(self.root, font=('ubuntu', 16, 'bold'), bg='black', fg='white', bd=0, text="POINTS") 
        self.show_points2.grid(row=8,column=1)
        
        self.win = Label(self.root)
        #self.win["image"] = self.photo[2]
        
        self.win.grid(row=0,column=0, rowspan=8,columnspan=8)

        self.start_time = time.clock()
        self.tick()
        self.window.set_visible(False)
        
        self.root.mainloop()

        ######################################
        ## Inicia modulo Sphinx - Gstreamer ##
        ######################################
    def init_gst(self):
        """Initialize the speech components"""
        self.pipeline = gst.parse_launch('gconfaudiosrc ! audioconvert ! audioresample '
                                         + '! vader name=vad auto-threshold=true '
                                         + '! pocketsphinx name=asr ! fakesink')
        asr = self.pipeline.get_by_name('asr')
        asr.connect('partial_result', self.asr_partial_result)
        asr.connect('result', self.asr_result)
        
        asr.set_property('configured', True)
        asr.set_property('lm', '/home/cy/sphinx/python/LanguageModel/instrucciones.lm')
        asr.set_property('dict', '/home/cy/sphinx/python/LanguageModel/instrucciones.dic')

        bus = self.pipeline.get_bus()
        bus.add_signal_watch()
        bus.connect('message::application', self.application_message)

        self.pipeline.set_state(gst.STATE_PAUSED)

    def asr_partial_result(self, asr, text, uttid):
        """Forward partial result signals on the bus to the main thread."""
        struct = gst.Structure('partial_result')
        struct.set_value('hyp', text)
        struct.set_value('uttid', uttid)
        asr.post_message(gst.message_new_application(asr, struct))

    def asr_result(self, asr, text, uttid):
        """Forward result signals on the bus to the main thread."""
        struct = gst.Structure('result')
        struct.set_value('hyp', text)
        struct.set_value('uttid', uttid)
        asr.post_message(gst.message_new_application(asr, struct))
        

    def application_message(self, bus, msg):
        """Receive application messages from the bus."""
        msgtype = msg.structure.get_name()
        if msgtype == 'partial_result':
            self.partial_result(msg.structure['hyp'], msg.structure['uttid'])
        if msgtype == 'listen_word':
            self.listen_word(msg.structure['hyp'], msg.structure['uttid'])
        elif msgtype == 'result':
            self.final_result(msg.structure['hyp'], msg.structure['uttid'])
            self.pipeline.set_state(gst.STATE_PAUSED)
            self.speak_button.set_active(False)

    def partial_result(self, hyp, uttid):
        """Delete any previous selection, insert text and select it."""
        # All this stuff appears as one single action
        self.textbuf.begin_user_action()
        self.textbuf.delete_selection(True, self.text.get_editable())
        self.textbuf.insert_at_cursor(hyp)
        ins = self.textbuf.get_insert()
        iter = self.textbuf.get_iter_at_mark(ins)
        iter.backward_chars(len(hyp))
        self.textbuf.move_mark(ins, iter)
        self.textbuf.end_user_action()

    def final_result(self, hyp, uttid):
        """Insert the final result."""
        # All this stuff appears as one single action
        self.textbuf.begin_user_action()
        self.textbuf.delete_selection(True, self.text.get_editable())
        self.textbuf.insert_at_cursor(hyp)
        self.textbuf.end_user_action()
        
        #self.buttons[0][0]["bg"] = "green"
        test = hyp
        if test == "PICK":
            self.buttons[self.PosY][self.PosX].invoke()
        if test == "LEFT":
            if self.PosX > 0:
                self.buttons[self.PosY][self.PosX]["bg"] = "black"
                self.PosX = self.PosX - 1
                self.buttons[self.PosY][self.PosX]["bg"] = "green"
        if test == "RIGHT":
            if self.PosX < 3:
                self.buttons[self.PosY][self.PosX]["bg"] = "black"
                self.PosX = self.PosX + 1
                self.buttons[self.PosY][self.PosX]["bg"] = "green"
        if test == "DOWN":
            if self.PosY < 3:
                self.buttons[self.PosY][self.PosX]["bg"] = "black"
                self.PosY = self.PosY + 1
                self.buttons[self.PosY][self.PosX]["bg"] = "green"
        if test == "UP":
            if self.PosY > 0:
                self.buttons[self.PosY][self.PosX]["bg"] = "black"
                self.PosY = self.PosY - 1
                self.buttons[self.PosY][self.PosX]["bg"] = "green"

        ####################
        ## Termina Sphinx ##
        ####################
        
    def listen_word(self,hyp,uttid):
        #self.pipeline.set_state(gst.STATE_PLAYING)
        self.buttons[0][0]["bg"] = "green"
        test = hyp
        if test == "UP":
            print "UP!"
            #self.buttons[0][0].invoke()

    # Funcion del boton speak 
    def speak_clicked(self, speak_button):
        """Handle button presses."""
        if speak_button.get_active():
            speak_button.set_label("Parar")
            self.pipeline.set_state(gst.STATE_PLAYING)
        else:
            speak_button.set_label("Hablar")
            vader = self.pipeline.get_by_name('vad')
            vader.set_property('silent', True)
    
    def activate_speak(self):
        while 1:
            self.speak_button.set_active(True)
            #self.pipeline.set_state(gst.STATE_PLAYING)
    
    # Funcion del boton Aceptar 
    def accept_clicked(self, accept_button):
        """Handle button presses."""
        if accept_button.get_active():
            self.t3.start()
            self.t4.start()

    def cancel_clicked(self, cancel_button):
        """Handle button presses."""
        if cancel_button.get_active():
            self.textbuf.set_text("")
    
    def check_end_game(self):
        if self.remaining == 0:
            
            self.end = Tk() 
            self.end["bg"] = "#3C3B37"
            self.end.title("DotAMemorY - Stats")

            #self.EndPhoto = PhotoImage(file="/home/cy/sphinx/python/images/win.gif")
            #self.win = Label(self.end, image=self.EndPhoto)
                        #win.pack(fill=BOTH, expand=1)
            #self.win.grid(row=0,column=0, rowspan=8,columnspan=8)    
            self.win["image"] = self.photo[2]
            points = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text = "YOUR POINTS ")
            points2 = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text = self.points)  
            moves = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text = "YOUR MOVES ")
            moves2 = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text = self.moves)
            time = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text="YOUR TIME ")
            time2 = Label(self.end, font=('ubuntu', 20, 'bold'), bg='#3C3B37', fg='white', bd=0, text= "%.2f" % self.time3)
            points.grid(row=9,column=0,columnspan=2)  
            points2.grid(row=9,column=2)
            moves.grid(row=10,column=0,columnspan=2)  
            moves2.grid(row=10,column=2)
            time.grid(row=11,column=0,columnspan=2)  
            time2.grid(row=11,column=2)
            self.end.mainloop()
        #######################################gnsiuashuithjiowr
    def set_state(self,button,card):
        if self.global_state == 1:
            if button != self.B1:
                self.global_state = 0
                self.B2 = button
                self.card2 = card
                if self.check_pair():
                    self.B1["state"] = DISABLED
                    self.B2["state"] = DISABLED
                    self.remaining = self.remaining - 1
                    self.points = self.points + 10                    
                elif self.check_pair() == False:
                    self.B1["image"] = self.photo[0]
                    self.B2["image"] = self.photo[0]
                    self.points = self.points - 1
                    self.card2 = -1
                    self.card2 = -1
            else:
                self.global_state = 1
            self.set_stats()
            self.check_end_game()

        elif self.global_state == 0:
            self.B1 = button
            self.card1 = card
            self.global_state = self.global_state + 1

    def check_pair(self):
        if self.card1 == self.card2:
            return True
        else:
            return False
    
    def set_stats(self):
        self.moves = self.moves + 1
        self.show_moves["text"] = self.moves
        self.show_points["text"] = self.points

    def restart_game(self):
        self.remaining = 8
        self.moves = 0
        self.points = 0
        self.root.destroy()
        t5 = threading.Thread(target=self.init_Tk)
        t5.start()
        print "hi there, everyone!"
        print "please wait..."
    
    def quit_game(self):
        self.root.destroy()
        self.window.destroy()
    
    def tick(self):        
        time2 = time.clock() - self.start_time
        #time2 = time.strftime('%H:%M:%S')
        if time2 != self.game_time-self.start_time: 
            self.game_time = time2 - self.start_time
            self.time3 = time2
            #time3 = time.strftime('%M:%S')
            self.show_time.config(text=int(self.time3)) 
        self.show_time.after(200, self.tick)
    
    ## Funciones de botones
    ## TODO optimizacion de codigo
    def button0_clicked(self):
        self.buttons[0][0]["image"] = self.heroPhoto[cards[0]]
        self.set_state(self.buttons[0][0],cards[0])

    def button1_clicked(self):
        self.buttons[0][1]["image"] = self.heroPhoto[cards[1]]
        self.set_state(self.buttons[0][1],cards[1])

    def button2_clicked(self):
        self.buttons[0][2]["image"] = self.heroPhoto[cards[2]]
        self.set_state(self.buttons[0][2],cards[2])

    def button3_clicked(self):
        self.buttons[0][3]["image"] = self.heroPhoto[cards[3]]
        self.set_state(self.buttons[0][3],cards[3])

    def button4_clicked(self):
        self.buttons[1][0]["image"] = self.heroPhoto[cards[4]]
        self.set_state(self.buttons[1][0],cards[4])

    def button5_clicked(self):
        self.buttons[1][1]["image"] = self.heroPhoto[cards[5]]
        self.set_state(self.buttons[1][1],cards[5])

    def button6_clicked(self):
        self.buttons[1][2]["image"] = self.heroPhoto[cards[6]]
        self.set_state(self.buttons[1][2],cards[6])

    def button7_clicked(self):
        self.buttons[1][3]["image"] = self.heroPhoto[cards[7]]
        self.set_state(self.buttons[1][3],cards[7])

    def button8_clicked(self):
        self.buttons[2][0]["image"] = self.heroPhoto[cards[8]]
        self.set_state(self.buttons[2][0],cards[8])

    def button9_clicked(self):
        self.buttons[2][1]["image"] = self.heroPhoto[cards[9]]
        self.set_state(self.buttons[2][1],cards[9])

    def button10_clicked(self):
        self.buttons[2][2]["image"] = self.heroPhoto[cards[10]]
        self.set_state(self.buttons[2][2],cards[10])

    def button11_clicked(self):
        self.buttons[2][3]["image"] = self.heroPhoto[cards[11]]
        self.set_state(self.buttons[2][3],cards[11])

    def button12_clicked(self):
        self.buttons[3][0]["image"] = self.heroPhoto[cards[12]]
        self.set_state(self.buttons[3][0],cards[12])
        
    def button13_clicked(self):
        self.buttons[3][1]["image"] = self.heroPhoto[cards[13]]
        self.set_state(self.buttons[3][1],cards[13])

    def button14_clicked(self):
        self.buttons[3][2]["image"] = self.heroPhoto[cards[14]]
        self.set_state(self.buttons[3][2],cards[14])

    def button15_clicked(self):
        self.buttons[3][3]["image"] = self.heroPhoto[cards[15]]
        self.set_state(self.buttons[3][3],cards[15])
        
app = DemoApp()
gtk.main()